#ifndef MERGE_BOX_H_JM_20120719
#define MERGE_BOX_H_JM_20120719

// ## 
#include "RootBox.h"

namespace jm4bbx {

	struct MergeBoxDescriptor {
		//static const char* BOX_ID;
		static const  groupType INPUT_GROUP_BEGIN;
		static const  groupType OUTPUT_GROUP;	
		static const  columnType INPUT_COLUMN;
		static const  columnType OUTPUT_COLUMN;
		static const  inType IN_ARC_BEGIN;
		static const  bobox::outarc_index_type OUT_ARC;
		static const char* MERGE_FACTOR_PARAM_NAME;


		static  inType getInArc(int index);

		static  groupType getInGroup(int index);
	};

	class MergeBox : public Box/*<MergeBoxDescriptor>*/ {		
		public:
			typedef MergeBoxDescriptor BoxIO;

			MergeBox(bobox::box_id_type id, bobox::box_tid_type tid, 
				bobox::request *req, const bobox::parameters &params) 
				: Box(id, tid, req, params) 
				, mergeFactor_(1) {

					if (params.has_parameter(BoxIO::MERGE_FACTOR_PARAM_NAME)) {
						params.get_parameter(BoxIO::MERGE_FACTOR_PARAM_NAME, mergeFactor_);
					}
			}


			virtual void initImpl() override {


				add_group(BoxIO::OUTPUT_GROUP, 
					BoxIO::OUTPUT_COLUMN, 
					get_output_descriptors(BoxIO::OUT_ARC));


				for (int i = 0; i < mergeFactor_; ++i) {

					add_group(BoxIO::getInGroup(i), 
						BoxIO::INPUT_COLUMN, 
						get_input_descriptors(BoxIO::getInArc(i)));
				}

				wait4Receive();
			}

			virtual void sync_mach_etwas() override {
				Group ig = get_group(BoxIO::INPUT_GROUP_BEGIN);
				if (ig.isPoisoned()/*poisoned_*/) {
					send_poisoned(BoxIO::OUT_ARC);
					return;
				}

				size_t maxIndex = 0;
				for (int i = 0; i < mergeFactor_; ++i) {
					maxIndex = std::max(maxIndex, get_group(BoxIO::getInGroup(i)).getReadEnd());//rdend_);
				}
				Group og = get_group(BoxIO::OUTPUT_GROUP);
				og.setWriteEnd(maxIndex);//wrend_ = maxInedex;
				og.setWritePosition(maxIndex);//wrpos_ = maxIndex;

				send(BoxIO::OUT_ARC, BoxIO::OUTPUT_GROUP);
				wait4Receive();
			}

	private:
		int mergeFactor_;

		void wait4Receive() {
			for (int i = 0; i < mergeFactor_; ++i) {
				receive(BoxIO::getInArc(i), BoxIO::getInGroup(i));
			}
		}
	};

} // namespace jm4bbx


#endif
